(require 'init-const)

(use-package restart-emacs
  :ensure t
  :commands (restart-emacs))

;;设置环境和编码格式
(set-language-environment 'chinese-gbk)
(prefer-coding-system 'utf-8-auto)

(if sys/macp
    (set-file-name-coding-system 'utf-8)
  (set-file-name-coding-system 'gbk))

;; Environment shell
(when (or sys/mac-x-p sys/linux-x-p (daemonp))
  (use-package exec-path-from-shell
    :ensure t
    :init
    (setq exec-path-from-shell-variables '("PATH" "MANPATH")
          exec-path-from-shell-arguments '("-l"))
    (exec-path-from-shell-initialize)))

;; saveplace 保存当前buffer的光标位置和文件路径，方便下一次打开的时候使用
;; emacs 本身自带
(use-package saveplace
    :ensure nil ;;本身自带 不需要下载
    :hook (after-init . save-place-mode)
    :init
    (setq save-place-file (expand-file-name ".cache/places" user-emacs-directory)))


(use-package recentf
    :ensure nil ;;本身自带 不需要下载
    :bind (("C-x C-r" . recentf-open-files))
    :hook (after-init . recentf-mode)
    :init (setq recentf-max-saved-items 300
            recentf-exclude
            '("\\.?cache" ".cask" "url" "COMMIT_EDITMSG\\'" "bookmarks"
              "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$"
              "\\.?ido\\.last$" "\\.revive$" "/G?TAGS$" "/.elfeed/"
              "^/tmp/" "^/var/folders/.+$" "^/ssh:" "/persp-confs/"
              (lambda (file) (file-in-directory-p file package-user-dir))))
    :config
    (push (expand-file-name recentf-save-file) recentf-exclude)
    (add-to-list 'recentf-filename-handlers #'abbreviate-file-name))

(use-package savehist
    :ensure nil
    :hook (after-init . savehist-mode)
    :init (setq enable-recursive-minibuffers t ; Allow commands in minibuffers
            history-length 1000
            savehist-file (expand-file-name ".cache/history" user-emacs-directory)
            savehist-additional-variables '(mark-ring
                                            global-mark-ring
                                            search-ring
                                            regexp-search-ring
                                            extended-command-history)
            savehist-autosave-interval 300))

;; (use-package simple
;;     :ensure nil
;;     :hook ((after-init . size-indication-mode)
;;           (text-mode . visual-line-mode)
;;           ((prog-mode markdown-mode conf-mode) . enable-trailing-whitespace))
;;     :init
;;     (setq column-number-mode nil
;;           line-number-mode nil
;;           ;; kill-whole-line t               ; Kill line including '\n'
;;           line-move-visual nil
;;           track-eol t                     ; Keep cursor at end of lines. Require line-move-visual is nil.
;;           set-mark-command-repeat-pop t)  ; Repeating C-SPC after popping mark pops it again

;;     ;; Visualize TAB, (HARD) SPACE, NEWLINE
;;     (setq-default show-trailing-whitespace nil) ; Don't show trailing whitespace by default
;;     (defun enable-trailing-whitespace ()
;;     "Show trailing spaces and delete on saving."
;;     (setq show-trailing-whitespace t)
;;     (add-hook 'before-save-hook #'delete-trailing-whitespace nil t))

;;   ;; Prettify the process list
;; )

(use-package simple
  :ensure nil
  :custom
  ;; show line/column/filesize in modeline
  (line-number-mode t)
  (column-number-mode t)
  (size-indication-mode t)
  ;; No visual feedback on copy/delete.
  (copy-region-blink-delay 0)
  (delete-pair-blink-delay 0)
  ;; confusing if no fringes (GUI only).
  (visual-line-fringe-indicators '(nil right-curly-arrow))
  ;; don't save current clipboard text before replacing it
  (save-interprogram-paste-before-kill nil)
  ;; eliminate duplicates
  (kill-do-not-save-duplicates t)
  ;; include '\n' when point starts at the beginning-of-line
  (kill-whole-line t)
  ;; show cwd when `shell-command' and `async-shell-command'
  (shell-command-prompt-show-cwd t)
  ;; show the name of character in `what-cursor-position'
  (what-cursor-show-names t)
  ;; List only applicable commands.
  ;;
  ;; ``` elisp
  ;; (defun foo ()
  ;;   (interactive nil org-mode)
  ;;   (message "foo"))
  ;; ```
  ;;
  ;; M-x foo should only be available in `org-mode` or modes derived from `org-mode`.
  (read-extended-command-predicate #'command-completion-default-include-p))

;; time
(use-package time
  :ensure nil
  :init (setq display-time-24hr-format t
              display-time-day-and-date t))

(when emacs/>=27p
  (use-package so-long
    :ensure nil
    :hook (after-init . global-so-long-mode)
    :config (setq so-long-threshold 4000)))

;;用y/n来代替yes/no
(fset 'yes-or-no-p 'y-or-n-p)

;;默认 mode
(setq-default major-mode 'text-mode
              fill-column 80
              tab-width 4
              indent-tabs-mode nil)     ; Permanently indent with spaces, never with TABs

(setq visible-bell t
      inhibit-compacting-font-caches t  ; Don’t compact font caches during GC.
      delete-by-moving-to-trash t       ; Deleting files go to OS's trash folder
      make-backup-files nil             ; Forbide to make backup files
      auto-save-default nil             ; Disable auto save

      uniquify-buffer-name-style 'post-forward-angle-brackets ; Show path if names are same
      adaptive-fill-regexp "[ t]+|[ t]*([0-9]+.|*+)[ t]*"
      adaptive-fill-first-line-regexp "^* *$"
      sentence-end "\\([。！？]\\|……\\|[.?!][]\"')}]*\\($\\|[ \t]\\)\\)[ \t\n]*"
      sentence-end-double-space nil)

;; 全屏设置
(when (display-graphic-p)
  (add-hook 'window-setup-hook #'fix-fullscreen-cocoa)
  (bind-keys ("C-<f11>" . toggle-frame-fullscreen)
             ("C-s-f" . toggle-frame-fullscreen) ; Compatible with macOS
             ("S-s-<return>" . toggle-frame-fullscreen)
             ("M-S-<return>" . toggle-frame-fullscreen)))

;; Non-nil means save word abbrevs too when files are saved.
(setq save-abbrevs nil)

;; 缩写 ;; turn on abbrev mode globally
(setq-default abbrev-mode t)

;; 将默认的find替换为fd
(if sys/macp
    (setq find-program "/opt/homebrew/bin/fd")
  (setq find-program "fd"))

;; 多窗口 防止其垂直拆分
(setq-default split-height-threshold nil)
;; prevent dired window split 3 columns
(setq-default split-width-threshold (* 2 (window-width)))
(setq recenter-positions '(top middle bottom))

;; project.el 功能 查找当前项目的根目录
(setq project-find-functions '(my/project-try-local project-try-vc))

;;禁用锁文件
(setq create-lockfiles nil)

;;允许查看匹配的括号对和其他字符
(show-paren-mode t)

;;将 .mm加入 objc-mode
(add-to-list 'auto-mode-alist '("\\.mm\\'" . objc-mode))

;;类似spacemacs中的M-m
(use-package general
  :ensure t
  :init
  (with-eval-after-load 'evil
    (general-add-hook 'after-init-hook
                      (lambda (&rest _)
                        (when-let ((messages-buffer (get-buffer "*Messages*")))
                          (with-current-buffer messages-buffer
                            (evil-normalize-keymaps))))
                      nil
                      nil
                      t))


  (general-create-definer global-definer
    :keymaps 'override
    :states '(insert emacs normal hybrid motion visual operator)
    :prefix "SPC"
    :non-normal-prefix "C-SPC")

  (defmacro +general-global-menu! (name infix-key &rest body)
    "Create a definer named +general-global-NAME wrapping global-definer.
Create prefix map: +general-global-NAME. Prefix bindings in BODY with INFIX-KEY."
    (declare (indent 2))
    `(progn
       (general-create-definer ,(intern (concat "+general-global-" name))
         :wrapping global-definer
         :prefix-map ',(intern (concat "+general-global-" name "-map"))
         :infix ,infix-key
         :wk-full-keys nil
         "" '(:ignore t :which-key ,name))
       (,(intern (concat "+general-global-" name))
        ,@body)))

  (general-create-definer global-leader
    :keymaps 'override
    :states '(emacs normal hybrid motion visual operator)
    :prefix ","
    "" '(:ignore t :which-key (lambda (arg) `(,(cadr (split-string (car arg) " ")) . ,(replace-regexp-in-string "-mode$" "" (symbol-name major-mode)))))))


(with-no-warnings
  ;; Key Modifiers
  (cond
   (sys/win32p
    ;; make PC keyboard's Win key or other to type Super or Hyper
    ;; (setq w32-pass-lwindow-to-system nil)
    (setq w32-lwindow-modifier 'super   ; Left Windows key
          w32-apps-modifier 'super)     ; Menu/App key
    (w32-register-hot-key [s-t]))
   (sys/mac-port-p
    ;; Compatible with Emacs Mac port
    (setq mac-option-modifier 'meta
          mac-command-modifier 'super)))

  ;; Optimization
  (when sys/win32p
    (setq w32-get-true-file-attributes nil   ; decrease file IO workload
          w32-pipe-read-delay 0              ; faster IPC
          w32-pipe-buffer-size (* 64 1024))) ; read more at a time (was 4K)
  (unless sys/macp
    (setq command-line-ns-option-alist nil))
  (unless sys/linuxp
    (setq command-line-x-option-alist nil))

  ;; Increase how much is read from processes in a single chunk (default is 4kb)
  (setq read-process-output-max (* 1024 1024)) ; 64kb

  ;; Don't ping things that look like domain names.
  (setq ffap-machine-p-known 'reject)

  (if sys/win32p
      (progn
        (defvar emax-root (concat (expand-file-name "~") "/emax"))
        (defvar emax-bin (concat emax-root "/bin"))
        (defvar emax-bin64 (concat emax-root "/bin64"))

        (setq exec-path (cons emax-bin exec-path))
        (setenv "PATH" (concat emax-bin ";" (getenv "PATH")))

        (setq exec-path (cons emax-bin64 exec-path))
        (setenv "PATH" (concat emax-bin64 ";" (getenv "PATH")))

        (setq emacsd-bin (concat user-emacs-directory "bin"))
        (setq exec-path (cons  emacsd-bin exec-path))
        (setenv "PATH" (concat emacsd-bin  ";" (getenv "PATH")))

        (setenv "PATH" (concat "C:\\msys64\\usr\\bin;C:\\msys64\\mingw64\\bin;" (getenv "PATH")))

        ;; (dolist (dir '("~/emax/" "~/emax/bin/" "~/emax/bin64/" "~/emax/lisp/" "~/emax/elpa/"))
        ;;   (add-to-list 'load-path dir))
        ))

  ;; Garbage Collector Magic Hack
  (use-package gcmh
    :ensure t
    :diminish
    :init
    (setq gcmh-idle-delay 5
          gcmh-high-cons-threshold #x1000000) ; 16MB
    (gcmh-mode 1)))

;; Encoding
;; UTF-8 as the default coding system
(when (fboundp 'set-charset-priority)
  (set-charset-priority 'unicode))

;; Keep clean but enable `menu-bar' in MacOS
(when (and (fboundp 'menu-bar-mode) (not (eq system-type 'darwin)))
  (menu-bar-mode -1))
(when (fboundp 'tool-bar-mode)
  (tool-bar-mode -1))
(when (fboundp 'set-scroll-bar-mode)
  (set-scroll-bar-mode nil))

(provide 'init-basic)